package gitobject;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import fileoperation.FileDeletion;
import fileoperation.FileReader;
import sha1.SHA1;
import repository.Repository;
import zlib.ZLibUtils;

public class Commit extends GitObject implements Serializable{
    protected String tree; 		// the sha1 value of present committed tree
    protected String parent = null; 	// the sha1 value of the parent commit
    protected String author; 	// the author's name and timestamp
    protected String committer; // the committer's info
    protected String message; 	// the commit memo
    protected HashMap<String , GitObject> commitTree = new HashMap<>();

    public String getParent(){return parent;}
    public String getTree(){return tree;}
    public String getAuthor(){return author;}
    public String getCommitter(){return committer;}
    public String getMessage(){return message;}
    public HashMap<String, GitObject> getCommitterTree(){return commitTree;}

    public Commit(){}

    public Commit(String author, String committer,String message) throws Exception {
        this.fmt = "commit"; // type of object
        this.committer = committer;
        this.author = author;
        this.message = message;


        File file = new File(Repository.getGitDir() + File.separator + "index");
        Index index = Index.deserialize(file);
        commitTree = index.fileOb;
//        System.out.println("-----" + len);
        String addHash = "";
        Iterator iterator = index.fileOb.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            GitObject value = (GitObject)entry.getValue();
            addHash += value.getKey();
        }
        this.key = SHA1.getHash(addHash);
//        System.out.println(this.key);

        File headFile = new File(Head.headPath);
        if (!headFile.exists()) {
            Head initial = new Head(this.key);
            initial.writeObject();
        } else {
            Head head = Head.deserialize();
            this.parent = head.getKey();
            head.setKey(this.key);
            head.writeObject();     //更新head
        }

        this.writeObject();

        Head newHead = Head.deserialize();

        Branch branch = new Branch(this.key, newHead.getBranchName());
        FileDeletion.deleteFile(file);
        this.value = "commit " + this.key + "\nparent " + this.parent + "\nauthor " + author + "\ncommitter "
                + committer + "\n" + this.message;

    }








    /**
     * Construct a commit directly from a file.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */
    public Commit(String treePath, String author, String committer, String message) throws Exception {
        this.fmt = "commit"; 	//type of object
        this.tree = new Tree(new File(treePath)).getKey(); 
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;
        
        key = genKey();
        compressWrite();

    }
    
    /**
     * Construct a commit from a built tree.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */
    public Commit(Tree t, String author, String committer, String message) throws Exception {
        this.fmt = "commigit resett"; 	//type of object
        this.tree = t.getKey(); 
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;
        key = genKey();
        compressWrite();
    }
    
    /**
     * Deserialize the commit object from its key(commitId)
     * @param commitId
     * @throws IOException
     */
    public Commit(String commitId) throws IOException {

    }
    /**
     * Generate the hash value of this commit.
     * @return key
     * */
    public String genKey() throws Exception {
        key = SHA1.getHash(value);
        return key;
    }


    public static Commit deserialize(String commitId) throws IOException, ClassNotFoundException {

        // 对文件对象进行反序列化


        File file = new File(path + File.separator + commitId.substring(0, 2) + File.separator + commitId.substring(2));
        if (file.exists()) {
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
            Commit commit = (Commit) objectInputStream.readObject();
            return commit;
        } else {
            System.out.println("Invalid Hash Value!");
            return null;
        }

    }


    /**
     * Get the parent commit from the HEAD file.
     * @return
     * @throws IOException
     */
    public static String getLastCommit() throws IOException {
        File HEAD = new File(Repository.getGitDir() + File.separator + "HEAD");

        String path = getValue(HEAD).substring(5).replace("\n", "");
        File branchFile = new File(Repository.getGitDir() + File.separator + path);

        if (branchFile.isFile()) {
            return getValue(branchFile);
        } else {
            return null;
        }
    }

    public String getValue() {
        return "commit " + this.key + "\nparent " + this.parent + "\nauthor " + author +
                 "\n\n\t" + this.message;
    }
}

